package com.jse.web;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Collection;
import java.util.Map;

import com.jse.Fs;
import com.jse.Js;
import com.jse.Jse;
import com.jse.Lang;
import com.jse.Log;
import com.jse.jdbc.Pager;
import com.jse.util.PatternPool;
import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpHandler;

public class Action implements HttpHandler {
	
	public void handle(HttpExchange ex) throws IOException {
		String path=ex.getRequestURI().getPath();
		Action.service(path,ex);
		Web.filter(ex,path,false);//执行后置处理
        ex.close();
	}

	public static void service(String path,HttpExchange ex) throws IOException {
		int suffixindex=path.lastIndexOf('.');
		String suffix=suffixindex==-1?"":path.substring(suffixindex+1);
		if(Web.isStatic(path,suffix)) {//静态
			try {
				View.staticforward.render(ex,path);
			} catch (Exception e) {
				e.printStackTrace();
			} finally {
				ex.close();
			}
			return;
		}
		try {
			var session=Web.session(ex);
			ex.getResponseHeaders().add("Set-Cookie","JSESSIONID="+session.getId());
		} catch (Exception e) {
			e.printStackTrace();
		}
		
		if(path.equals("/jse")) {
			Js.evalFile(Jse.jspath()+"/jse.js", null);
			View.not.render(ex,null);
			return;
		}
		if(!Web.filter(ex, path, true)) {
			return;
		}
//		System.out.println("addr: " + httpExchange.getRemoteAddress() +     // 客户端IP地址
//                "; protocol: " + httpExchange.getProtocol() +               // 请求协议: HTTP/1.1
//                "; method: " + httpExchange.getRequestMethod() +            // 请求方法: GET, POST 等
//                "; URI: " + httpExchange.getRequestURI());                  // 请求 URI
//		Web.cookies(ex);
		String mapping=path.substring(0,path.length()-suffix.length());
		mapping=mapping.endsWith("/")?mapping.concat("/index"):mapping;
		if("vue".equals(suffix)){
			vue(ex,path,suffix);
		}else if(suffix.length()==0||"html".equals(suffix)){//后缀空
			try {
				empty(ex, path, suffix);
			} catch (Exception e) {
				e.printStackTrace();
			}
		}else if("json".equals(suffix)){
			var json=Jse.webapp(ex.getLocalAddress().getHostName())+path;
			if(Fs.exists(json)) {
				View.json.render(ex,Fs.read(json));
			}
			json=Jse.jspath(ex.getLocalAddress().getHostName())+path;
			if(Fs.exists(json)) {
				View.json.render(ex,Fs.read(json));
			}
			json=json.substring(0,json.length()-2);
			if(Fs.exists(json)) {
				try {
					empty(ex, path, suffix);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		}else {
			var webapp=Jse.webapp(ex.getLocalAddress().getHostName());
			var p=Path.of(webapp,path);
			if(Files.exists(p)) {
				View.staticforward.render(ex,path);
				return;
			}
			var jspath=Jse.jspath(ex.getLocalAddress().getHostName());
			var js=Path.of(jspath,mapping+".js");
			if(Files.exists(js)){
				View.ret.render(ex,Js.cFun(js,suffix,ex));
			}
		}
	}
	
	private static void vue(HttpExchange ex,String path,String suffix) throws IOException {//处理vue
		Tbl tbl=new Tbl(ex);//转换参数
		String mapping=path.substring(0,path.length()-suffix.length());
		mapping=mapping.endsWith("/")?mapping.concat("/index"):mapping;
		var jspath=Jse.jspath(tbl.getServerName());
		var webapp=Jse.webapp(tbl.getServerName());
		var vue=Path.of(jspath,mapping.concat(".vue"));
		if(Files.exists(vue)) {
			var s=Fs.readString(jspath,mapping.concat(".vue"),Map.of("tpl","js","p",tbl));
			View.text.render(ex,s);
		}
		vue=Path.of(webapp,mapping+".vue");
		if(Files.exists(vue)){
			var s=Fs.readString(webapp,mapping.concat(".vue"),Map.of("tpl","js","p",tbl));
			View.text.render(ex,s);
		}
	}
	
	private static void empty(HttpExchange ex
			,String path,String suffix) throws Exception {//默认空后缀
		try {
			var jspath=Jse.jspath(ex.getLocalAddress().getHostName());
			Tbl tbl=new Tbl(ex);//转换参数
			int len=suffix.length()>0?suffix.length()+1:0;
//			String mapping=Web.mapping(url,suffix,tbl);//处理/id
			ScopedValue.where(Web.RQRS,tbl).call(()->{
				String mapping=path.substring(0,path.length()-len);
				mapping=mapping.endsWith("/")?mapping.concat("/index"):mapping;
				var reg=PatternPool.get("/([0-9]+)$").matcher(mapping);
				if(reg!=null&&reg.find()) {
					var id=reg.group().substring(1);
					tbl.put("id",id);
					mapping=mapping.substring(0,mapping.length()-id.length())+"id";
				}
				ex.setAttribute("p",tbl);
				var webapp=Jse.webapp(tbl.getServerName());
				var js=Path.of(jspath+mapping+".js");
				Object obj=null;
				if(Files.exists(js)) {
					try {
						obj=Js.cFun(js,"main",new Object[]{tbl,ex});
					} catch (Exception e) {
						e.printStackTrace();
						throw new RuntimeException(e);}
				}
				if(suffix.equals("json")) {
					View.json.render(ex,obj);
					return null;
				}
				var ht=Lang.def(ex.getAttribute("@page"),mapping+".html");
				var htm=webapp+ht;
				var htmm=webapp+"/m"+ht;//手机端页面
				if(obj instanceof View v)v.render(ex,null);
				else if(Files.exists(Path.of(htm))) {
					try {
						ex.setAttribute("obj",obj);
						View.tpl.render(ex,htm);
					} catch (Throwable e) {
						e.printStackTrace();
					}
				}else if(Lang.isMobile(ex.getRequestHeaders().getFirst("user-agent"))&&Files.exists(Path.of(htmm))) {
					ex.setAttribute("obj",obj);View.tpl.render(ex,htmm);
				}else if(Files.exists(Path.of(jspath,mapping+".vue"))) {
					var s=Fs.readString(jspath,mapping+".vue",Map.of("tpl","js","p",tbl));
					View.text.render(ex,s);
				}else if(Files.exists(Path.of(webapp,mapping+".vue"))) {
					var s=Fs.readString(webapp,mapping+".vue",Map.of("tpl","js","p",tbl));
					View.text.render(ex,s);
				}else if(Files.exists(Path.of(jspath+mapping+".html"))) {
					View.tpl.render(ex,jspath+mapping+".html");
				}
				else if(obj instanceof Map||obj instanceof Collection||obj instanceof Pager) {
					View.json.render(ex, obj);
				}else if(obj instanceof String s) {
					View.str.render(ex,s);
				}
				else {
					View.not.render(ex,null);
				}
				return null;
			});
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			Log.get("jseservlet").debug("结束url:{}",path);
		}
	}
}
